#include "packet.h"
#include <pthread.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <list>

// IO Thread declaration
void * serv_io_thread_func(void * arg);

class ClientData {
public:
	struct sockaddr_in addr;
	uint32_t snd_seq;
	uint32_t rcv_seq;
	uint32_t conn_id;
	std::list<Packet> out_buf;
	std::list<Packet> in_buf;
	pthread_mutex_t in_lock;
	pthread_mutex_t out_lock;
	time_t last_io_event;
	unsigned int epoch_counter;
	bool compare(struct sockaddr_in * a, uint32_t c_id);
};

class ServerBuffer {
public:
	// Connection data
	int sock;
	struct sockaddr_in server;

	// Concurrency data
	pthread_t io_thread;
	bool running;
	pthread_mutex_t client_lock;
	pthread_cond_t data_received;
	pthread_cond_t ack_received;
	int epoch;
	int numepochs;

	// State
	int state;
	char * errmsg;

	std::list<ClientData*> connected_clients;
	ServerBuffer(uint16_t port, int epoch_len, int n);
	int read(uint8_t * data, uint32_t * conn_id);
	int write(uint32_t conn_id, uint8_t * data, uint32_t len);
	void print_error(int err, const char * msg);
	uint32_t get_next_id();
	std::list<ClientData*>::iterator insert_client(ClientData* new_client);
	void finish();
};


